//  轮播图 的 构造函数
//  参数1 要生成轮播图的标签对象
//  参数2 生成轮播图根据的数据数组
class setBanner{
    // 构造器 存储 参数 
    constructor(element , array){
        // 定义属性 存储 参数 
        this.ele = element ;
        this.arr = array ;

        // 之前的全局变量 都以 属性的形式存储 
        // 定义属性 存储 数据 所有函数都可以调用
        this.length = this.arr.length ;
        this.oUl ;
        this.oOl ;
        this.oUlLis;
        this.oOlLis;
        this.liWidth;
        this.time;
        this.index = 1 ; 
        this.res = true ;
    }

    // 入口函数 
    // 入口函数 调用执行 当前面向对象编程 需要执行的所有程序
    // 入口函数 必须 命名为 init
    init(){
        // 调用函数 动态生成页面
        this.setPage();
        // 调用函数 自动轮播
        this.autoLoop();
        // 调用函数 鼠标的移入移出
        this.setMouse();
        // 调用函数 点击事件
        this.setClick();
        // 调用函数 浏览器隐藏
        this.setHide();
    }

    // 函数方法1 动态生成页面
    setPage(){
        // 创建标签对象
        this.oUl = document.createElement('ul');
        this.oOl = document.createElement('ol');
        const oDiv = document.createElement('div');

        // 定义变量 存储 ul>li  ol>li 字符串
        let ulStr = '';
        let olStr = '';

        // 标签写入内容
        this.arr.forEach((item , key)=>{
            ulStr += `<li><img src="./images/${item.src}"></li>`;
            olStr += key === 0 ? `<li class="active" name="focus" num="${key}"></li>` : `<li name="focus" num="${key}"></li>` ;
        })


        this.oUl.innerHTML = ulStr ;
        this.oOl.innerHTML = olStr ;
        oDiv.innerHTML = '<a name="left" href="JavaScript:;">&lt;</a><a name="right" href="JavaScript:;">&gt;</a>'
    
        // 标签节点 写入 页面
        this.ele.appendChild( this.oUl );
        this.ele.appendChild( this.oOl );
        this.ele.appendChild( oDiv );

        // 获取 ul>li  ol>li
        this.oUlLis = this.oUl.querySelectorAll('li');
        this.oOlLis = this.oOl.querySelectorAll('li');

        //获取 ul>li 标签 宽度 
        this.liWidth = parseInt( window.getComputedStyle( this.oUlLis[0] ).width );

        // 克隆标签
        const cloneFirst = this.oUlLis[0].cloneNode(true);
        const cloneLast = this.oUlLis[this.oUlLis.length-1].cloneNode(true);

        // 第一个写入ul最后 
        // 最后一个写入ul起始
        this.oUl.appendChild( cloneFirst );
        this.oUl.insertBefore( cloneLast , this.oUlLis[0] );
        
        // 重新设定 ul 宽度 和 定位
        this.oUl.style.width = (this.length+2) * this.liWidth + 'px';
        this.oUl.style.left = -this.liWidth + 'px' ;
    }

    // 函数方法2 自动轮播
    autoLoop(){
        this.time = setInterval( ()=>{
            // 变量累加1
            this.index++ ;

            // 调用 焦点样式函数 设定焦点样式
            this.setFocusStyle();

            // 调用 move() 运动函数 完成 ul标签的定位切换
            // 在 构造函数中 调用 实例化对象的属性属性值是 this.属性的语法
            // 在 构造函数中 调用 构造函数prototype中的函数方法 是 this.函数 的语法
            // this.loopEnd  是 回调函数的语法形式 在 move() 函数 的 定时器 中 
            // 调用 this.loopEnd 这个函数程序 
            // 回调函数 this指向 一定不是 实例化对象 
            // 通过 bind语法 创建一个新的函数 和 this.loopEnd 函数程序相同
            // 同时 指定 这个新的函数 this指向 是 当前构造函数的this指向 也就是 实例化对象
            move( this.oUl , {left : -this.index*this.liWidth} , this.loopEnd.bind(this) );
        } , 3000)


    }

    // 函数方法3 运动结束 执行的函数程序
    loopEnd(){

        // 判断 index 的数值
        if( this.index === this.length+2-1 ){
            this.index = 1;
            this.oUl.style.left = -this.index*this.liWidth + 'px' ;
        }else if( this.index === 0 ){
            this.index = this.length+2-1-1;
            this.oUl.style.left = -this.index*this.liWidth + 'px' ;
        }

        // 给变量赋值原始值
        this.res = true ;
    }

    // 函数方法4 设定焦点样式
    setFocusStyle(){
        // 循环遍历清除所有的 ol>li class,active
        this.oOlLis.forEach( item => {
            item.classList.remove('active')
        })

        // 判断 index的数值
        if( this.index === this.length+2-1 ){
            this.oOlLis[0].classList.add('active');
        }else if( this.index === 0 ){
            this.oOlLis[this.oOlLis.length-1].classList.add('active');
        }else {
            this.oOlLis[this.index-1].classList.add('active');
        }
    }

    // 函数方法5 鼠标移入移出
    setMouse(){
        this.ele.addEventListener( 'mouseenter' , ()=>{
            clearInterval( this.time );
        })

        this.ele.addEventListener( 'mouseleave' , ()=>{
            this.autoLoop();
        })
    }

    // 函数6 点击事件
    setClick(){
        this.ele.addEventListener( 'click' , e => {
            if( e.target.getAttribute('name') === 'left' ){
                if( this.res ){
                    this.res = false;
                }else{
                    return ;
                }

                this.index-- ;

                this.setFocusStyle();

                move( this.oUl , {left : -this.index*this.liWidth} , this.loopEnd.bind(this) );
            
            
            }else if( e.target.getAttribute('name') === 'right' ){
                if( this.res ){
                    this.res = false;
                }else{
                    return ;
                }

                this.index++ ;

                this.setFocusStyle();

                move( this.oUl , {left : -this.index*this.liWidth} , this.loopEnd.bind(this) );
            
            }else if( e.target.getAttribute('name') === 'focus' ){
                if( this.res ){
                    this.res = false;
                }else{
                    return ;
                }

                this.index = e.target.getAttribute('num') -0 +1 ;

                this.setFocusStyle();

                move( this.oUl , {left : -this.index*this.liWidth} , this.loopEnd.bind(this) );
            
            }


        })
    }

    // 函数7 浏览器隐藏
    setHide(){
        document.addEventListener( 'visibilitychange' , () => {
            if( document.visibilityState === 'hidden' ){
                clearInterval( this.time);
            }else if( document.visibilityState === 'visible' ){
                this.autoLoop() ;
            }   
        })
    }

}